<template>
  <div class="custom-form-wrap">
    <a-form-model
      ref="form"
      :layout="formLayout"
      :model="formModel"
      :rules="formRules"
    >
      <Layout v-bind="$attrs" :optionList="options">
        <template slot-scope="{ row, prop }">
          <components
            :is="row.component"
            :instance="row"
            v-on="$listeners"
            @change="value => updateFormModel(prop, value)"
            @enterChange="enterChange"
            @setFormModelValue="setFormModel"
            @resetOptDefault="resetOptDefaultValue"
            :ref="row.prop"
            :uploadArray="uploadTypeMap"
          >
          </components>
        </template>
      </Layout>
    </a-form-model>
  </div>
</template>

<script>
import { cloneDeep } from 'lodash'
import Layout from './formLayout.vue'
import AInput from './components/Ainput.vue'
import ADate from './components/ADate.vue'
import Captcha from './components/Captcha.vue'
import ATextArea from './components/ATextArea.vue'
import ARadioGroup from './components/ARadioGroup.vue'
import ASelect from './components/ASelect'
import AUpload from './components/AUpload'
import AMultipleSelect from './components/AMultipleSelect'
import AUploadMultiple from './components/AUploadMultiple'
import RichTextEdit from './components/RichTextEdit'
import OtherButton from './components/OtherButton.vue'
import EditTable from './components/EditTable'
import SpliceUploadVideo from './components/SliceUploadVideo'
import AInputAndButton from './components/AInputAndButton'
import Acascader from './components/Acascader.vue'
import AcascaderInput from './components/AcascaderInput.vue'

export default {
  props: {
    optionList: Array, // 表单的配置
    formRules: Object, // 表单的规则配置
    formLayout: String, // 表单的布局方式
    defaultModel: Object, // 默认值
    isErrorMessage: {
      // 是否使用轻提示的形式展示表单的填写错误
      type: Boolean,
      default: () => true
    },
    uploadTypeMap: Array
  },
  data() {
    return {
      options: [], // 配置文件
      formModel: {} // 表单的value
    }
  },
  watch: {
    defaultModel: {
      // 默认值更新
      handler() {
        this.initOptions()
      },
      immediate: true,
      deep: true
    },
    optionList: {
      handler(newVal) {
        this.options = newVal
      },
      deep: true,
    },
  },
  components: {
    AInput,
    ADate,
    Captcha,
    ATextArea,
    ARadioGroup,
    RichTextEdit,
    Layout,
    AUpload,
    ASelect,
    AUploadMultiple,
    AMultipleSelect,
    OtherButton,
    EditTable,
    SpliceUploadVideo,
    AInputAndButton,
    Acascader,
    AcascaderInput
  },
  methods: {
    // 给表单设置默认值
    initOptions() {
      this.options = cloneDeep(this.optionList)
      if (!this.defaultModel) return // 如果没有传递默认值，直接退出
      this.options.forEach(item => {
        const defaultV = this.defaultModel[item.prop]
        item.prop && this.$set(this.formModel, item.prop, defaultV)
        this.$set(item, 'defaultValue', defaultV)
        // this.$set(item, 'techPatents', this.defaultModel.techPatents)
        const { isCustomList, customRequestList } = item
        if (isCustomList && customRequestList) {
          // 自定义的list
          customRequestList.call(this, item)
        }
      })
    },
    // 更新表单组件的数据
    updateFormModel(prop, value) {
      this.setFormModel(prop, value)
      this.resetOptDefaultValue(prop, value)
      this.$emit('selectChange',prop, value)
    },
    updateFormSelectOptions(prop, list) {
      this.$refs[prop].update(list)
    },
    // 设置对应配置中的默认值
    resetOptDefaultValue(prop, value) {
      this.options.forEach(item => {
        // 同步更新配置中对应的值
        if (item.prop === prop) {
          item.defaultValue = value
        }
      })
    },
    // 清空formModel中的某个值
    setFormModel(prop, value) {
      this.formModel[prop] = value
    },
    // 重置表单
    resetForm() {
      this.$refs.form.resetFields()
      this.$emit('reseted-form', true)
    },
    // 清除校验信息
    clearValidateForm() {
      this.$refs.form.clearValidateForm()
      this.$emit('cleared-form', true)
    },
    // 校验表单
    validatedForm(cb, customValidator) {
      let validateResult = false
      this.$refs.form.validate((validate, instance) => {
        if (!validate) {
          // 报错
          if (!this.isErrorMessage) return
          Object.keys(instance).map(key => {
            const element = instance[key]
            element.forEach(errs => {
              this.$apiStatusHandler(99, errs.message || '表单填写有误')
            })
            validateResult = false
            return false
          })
        } else {
          validateResult = true
          if (customValidator) {
            const v = customValidator.call(this, this.formModel)
            validateResult = v
          }
          if (cb) {
            // 如果有回调执行回调
            cb()
          }
        }
      })
      return validateResult
    },
    // 回车事件
    enterChange(val) {
      this.$emit('enterChange', val)
    }
  }
}
</script>
